﻿using System;
using System.IO;
using System.Xml;

public class XmlHelper
{
    public static XmlAttribute GetAttr(XmlNode node, string attrName, bool optional = false)
    {
        var attr = node.Attributes[attrName];
        if (attr == null && !optional)
        {
#if USE_LOGWRAPPER
            LogWrapper.LogError(GetNodePath(node), " don't contain an attr named ", attrName);
#endif
        }

        return attr;
    }

    public static XmlNode GetChild(XmlNode node, string childName, bool optional = false)
    {
        XmlNode childNode = node[childName];
        if (childNode == null && !optional)
        {
#if USE_LOGWRAPPER
            LogWrapper.LogError(GetNodePath(node), " don't contain an node named ", childName);
#endif
        }

        return childNode;
    }

    public static XmlNodeList GetChildNodeList(XmlNode node, string childName, string nodeName, bool optional = false)
    {
        XmlNode childNode = node[childName];
        if (childNode == null && !optional)
        {
#if USE_LOGWRAPPER
            LogWrapper.LogError(GetNodePath(node), " don't contain an node named ", childName);
#endif
        }
        else if (childNode != null)
        {
            return childNode.SelectNodes(nodeName);
        }

        return null;
    }

    public static string GetNodePath(XmlNode node)
    {
        if (node.ParentNode == null)
            return node.Name;
        return GetNodePath(node.ParentNode) + "/" + node.Name;
    }

    #region Parse return status

    public static bool ParseAttrInt(XmlNode node, string attrName, out int value, bool optional = false)
    {
        var attr = GetAttr(node, attrName, optional);
        if (attr == null)
        {
            value = 0;
            return false;
        }

        if (!int.TryParse(attr.InnerText, out value))
        {
#if USE_LOGWRAPPER
            LogWrapper.LogError("{0}.{1} isn't an int.", GetNodePath(node), attrName);
#endif
            return false;
        }

        return true;
    }

    #endregion


    public static XmlNode ReadXML(string fullpath, ref byte[] bytValue)
    {
        try
        {
            var flieContext = File.ReadAllBytes(fullpath);
            bytValue = flieContext;

            var xmlDoc = new XmlDocument();
            var settings = new XmlReaderSettings();
            settings.IgnoreComments = true;

            var strUTF8Context = XMLBuffHelper.GetUTF8String(flieContext);
            var strUTF8ConReader = new StringReader(strUTF8Context);
            var reader = XmlReader.Create(strUTF8ConReader, settings);

            xmlDoc.Load(reader);

            var rootNode = xmlDoc.LastChild;

            return rootNode;
        }
        catch (Exception e)
        {
            LogWrapper.LogError("ReadXML ", fullpath, e.Message);
            return null;
        }
    }

    #region Parse return result

    public static int ParseInt(XmlNode node, int default_value = 0)
    {
        int value;
        if (!int.TryParse(node.InnerText, out value))
        {
#if USE_LOGWRAPPER
            LogWrapper.LogError(GetNodePath(node), " isn't an int.");
#endif
            return default_value;
        }

        return value;
    }

    public static long ParseLong(XmlNode node)
    {
        long value;
        if (!long.TryParse(node.InnerText, out value))
        {
#if USE_LOGWRAPPER
            LogWrapper.LogError(GetNodePath(node), " isn't a long.");
#endif
            return 0;
        }

        return value;
    }

    public static float ParseFloat(XmlNode node)
    {
        float value;
        if (!float.TryParse(node.InnerText, out value))
        {
#if USE_LOGWRAPPER
            LogWrapper.LogError(GetNodePath(node), " isn't a float.");
#endif
            return 0;
        }

        return value;
    }

    public static bool ParseBool(XmlNode node, bool default_value)
    {
        var value = false;
        if (!bool.TryParse(node.InnerText, out value))
        {
#if USE_LOGWRAPPER
            LogWrapper.LogError(GetNodePath(node), " isn't a bool.");
#endif
            return default_value;
        }

        return value;
    }

    public static int ParseAttrInt(XmlAttribute attr, int default_value = 0)
    {
        int value;
        if (!int.TryParse(attr.InnerText, out value))
        {
#if USE_LOGWRAPPER
            LogWrapper.LogError(GetNodePath(attr.OwnerElement) + "." + attr.Name, " isn't an int.");
#endif
            return default_value;
        }

        return value;
    }

    public static float ParseAttrFloat(XmlAttribute attr, float default_value = 0)
    {
        float value;
        if (!float.TryParse(attr.InnerText, out value))
        {
#if USE_LOGWRAPPER
            LogWrapper.LogError(GetNodePath(attr.OwnerElement) + "." + attr.Name, " isn't a float.");
#endif
            return default_value;
        }

        return value;
    }

    public static bool ParseAttrBool(XmlAttribute attr, bool default_value)
    {
        bool value;
        if (!bool.TryParse(attr.InnerText, out value))
        {
#if USE_LOGWRAPPER
            LogWrapper.LogError(GetNodePath(attr.OwnerElement) + "." + attr.Name, " isn't a bool.");
#endif
            return default_value;
        }

        return value;
    }

    public static int ParseAttrInt(XmlNode node, string attrName, bool optional = false)
    {
        var attr = GetAttr(node, attrName, optional);
        if (attr == null)
        {
            return 0;
        }

        return ParseAttrInt(attr);
    }

    public static int ParseAttrInt(XmlNode node, string attrName, int default_value)
    {
        var attr = GetAttr(node, attrName, true);
        if (attr == null)
        {
            return default_value;
        }

        return ParseAttrInt(attr, default_value);
    }

    public static float ParseAttrFloat(XmlNode node, string attrName, bool optional = false)
    {
        var attr = GetAttr(node, attrName, optional);
        if (attr == null)
        {
            return 0;
        }

        return ParseAttrFloat(attr);
    }

    public static float ParseAttrFloat(XmlNode node, string attrName, float default_value)
    {
        var attr = GetAttr(node, attrName, true);
        if (attr == null)
        {
            return default_value;
        }

        return ParseAttrFloat(attr, default_value);
    }

    public static bool ParseAttrBool(XmlNode node, string attrName)
    {
        var attr = GetAttr(node, attrName);
        if (attr == null)
        {
            return false;
        }

        return ParseAttrBool(attr, false);
    }

    public static bool ParseAttrBool(XmlNode node, string attrName, bool default_value)
    {
        var attr = GetAttr(node, attrName, true);
        if (attr == null)
        {
            return default_value;
        }

        return ParseAttrBool(attr, default_value);
    }

    public static string ParseAttrString(XmlNode node, string attrName, bool optional = false)
    {
        var attr = GetAttr(node, attrName, optional);
        if (attr == null)
        {
            return null;
        }

        return attr.InnerText;
    }

    public static string ParseAttrString(XmlNode node, string attrName, string default_value)
    {
        var attr = GetAttr(node, attrName, true);
        if (attr == null)
        {
            return default_value;
        }

        return attr.InnerText;
    }

    public static int ParseChildInt(XmlNode node, string childName, bool optional = false)
    {
        var childNode = GetChild(node, childName, optional);
        if (childNode == null)
        {
            return 0;
        }

        return ParseInt(childNode);
    }

    public static int ParseChildInt(XmlNode node, string childName, int default_value)
    {
        var childNode = GetChild(node, childName, true);
        if (childNode == null)
        {
            return default_value;
        }

        return ParseInt(childNode, default_value);
    }

    public static long ParseChildLong(XmlNode node, string childName, bool optional = false)
    {
        var childNode = GetChild(node, childName, optional);
        if (childNode == null)
        {
            return 0;
        }

        return ParseLong(childNode);
    }

    public static float ParseChildFloat(XmlNode node, string childName, bool optional = false)
    {
        var childNode = GetChild(node, childName, optional);
        if (childNode == null)
        {
            return 0;
        }

        return ParseFloat(childNode);
    }

    public static bool ParseChildBool(XmlNode node, string childName)
    {
        var childNode = GetChild(node, childName);
        if (childNode == null)
        {
            return false;
        }

        return ParseBool(childNode, false);
    }

    public static bool ParseChildBool(XmlNode node, string childName, bool default_value)
    {
        var childNode = GetChild(node, childName, true);
        if (childNode == null)
        {
            return default_value;
        }

        return ParseBool(childNode, default_value);
    }

    public static string ParseChildString(XmlNode node, string childName, bool optional = false)
    {
        var childNode = GetChild(node, childName, optional);
        if (childNode == null)
        {
            return null;
        }

        return childNode.InnerText;
    }

    #endregion
}